SBERT-based Similarity (SBERT-Sim)

在自然語言處理中,想知道「兩句話是否在講同樣的意思」是一個關鍵問題。例如:「The patient has a fever」與「The patient is running a temperature」雖然用詞不同,但語意幾乎相同。傳統的詞彙重疊方法(如 ROUGE)無法很好地捕捉這種語意等價,因此研究者開發了 Sentence-BERT(SBERT)。它可以把每個句子轉換成一個「語意向量」,並用餘弦相似度(cosine similarity)衡量兩句話的語意接近程度(Reimers & Gurevych, 2019)。

一、SBERT 的原理

BERT 模型能理解語言,但每次比較兩個句子時都要「同時輸入」它們,這樣計算量非常大(比較 10,000 句話要花 65 小時)。 SBERT 解決了這個問題,讓每個句子能先被轉換成一個固定長度的語意向量(embedding)。 這樣,系統只需比較向量之間的距離就能知道語意相似度。

這個設計稱為「Siamese Network(孿生網路結構)」:

這種方式就像是把句子放進同一張「語意地圖」上:
距離越近,意思越接近。

二、計算方式

SBERT 最常用的比較方法是餘弦相似度(cosine similarity)

similarity=uv||u||×||v||

舉例來說:

這表示前者語意相近,後者語意無關。

三、結果的意義

SBERT-Sim 的輸出是一個介於 -1 到 1 之間的數字:

這個指標特別適合:

四、Python 範例

以下展示如何用 sentence-transformers 套件計算 SBERT 語意相似度:

# 安裝套件
# pip install sentence-transformers

from sentence_transformers import SentenceTransformer, util

# 載入 SBERT 模型(輕量且常用的版本)
# model = SentenceTransformer('all-MiniLM-L6-v2')

# 處理中文的模型
model_name = "shibing624/text2vec-base-chinese"
model = SentenceTransformer(model_name)

# 兩個要比較的句子
sent1 = "這位病人出現發燒、頭痛與咳嗽的症狀。"
sent2 = "患者有發燒且頭痛,並伴有咳嗽。"

# 將句子轉為向量
emb1 = model.encode(sent1, convert_to_tensor=True)
emb2 = model.encode(sent2, convert_to_tensor=True)
 

# 計算餘弦相似度

cos_sim = util.pytorch_cos_sim(emb1, emb2).item()
cos_sim

Reference

Reimers, N., & Gurevych, I. (2019). Sentence-BERT: Sentence Embeddings using Siamese BERT-Networks. Proceedings of the 2019 Conference on Empirical Methods in Natural Language Processing and the 9th International Joint Conference on Natural Language Processing (EMNLP-IJCNLP), 3980–3990. https://doi.org/10.18653/v1/D19-1410